package com.godenwater.recv.server.yf;

import com.godenwater.core.container.Module;
import com.godenwater.recv.manager.*;
import com.godenwater.recv.server.all.RtuServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Created by Li on 2017/3/11.
 */
public class YFRtuServer {
    private static Logger logger = LoggerFactory.getLogger(RtuServer.class);

    private long startDate = System.currentTimeMillis();

    private static YFRtuServer instance;

    private boolean RUNNING = false;
    // ----------------------------------------------------------------------
    /**
     * All modules loaded by this server
     */
    private Map<Class, Module> modules = new LinkedHashMap<Class, Module>();

    private ClassLoader loader;

    // 计数
    public final AtomicInteger wc = new AtomicInteger();

    /**
     * Returns a singleton instance of XMPPServer.
     *
     * @return an instance.
     */
    public static YFRtuServer getInstance() {
        if (instance == null) {
            instance = new YFRtuServer();
        }
        return instance;
    }

    /**
     * Creates a server and starts it.
     */
    private YFRtuServer() {
        if (instance != null) {
            throw new IllegalStateException("RTU>> YY server is already running");
        }
        instance = this;
    }

    /**
     * 初始化数据
     */
    public void initialize() {

        startDate = System.currentTimeMillis();

        loader = Thread.currentThread().getContextClassLoader();

    }

    /**
     * 加载内部模块
     */
    private void loadModules() {

        loadModule(YfConnectionManager.class.getName()); // 加载连接管理器
//        loadModule(SessionManager.class.getName()); // 加载会话管理
//
//        loadModule(StationManager.class.getName()); // 加载测站信息
//        loadModule(MessageManager.class.getName()); // 加载会话管理
//        loadModule(TaskManager.class.getName()); // 加载任务管理器
//
//        loadModule(MonitorManager.class.getName()); // 加载监控终端管理器

    }

    /**
     * 加载模块
     *
     * @param module
     */
    private void loadModule(String module) {
        System.out.println(">> Load " + module + "...");
        try {
            Class modClass = loader.loadClass(module);
            Module mod = (Module) modClass.newInstance();
            this.modules.put(modClass, mod);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("admin.error", e);
        }
    }

    private void initModules() {
        for (Module module : modules.values()) {
            boolean isInitialized = false;
            try {
                module.initialize();
                isInitialized = true;
            } catch (Exception e) {
                e.printStackTrace();
                // Remove the failed initialized module
                this.modules.remove(module.getClass());
                if (isInitialized) {
                    module.stop();
                    module.destroy();
                }
                logger.error("initModules.error", e);
            }
        }
    }

    private void startModules() {
        for (Module module : modules.values()) {
            boolean started = false;
            try {
                module.start();
            } catch (Exception e) {
                if (started && module != null) {
                    module.stop();
                    module.destroy();
                }
                logger.error("startModules.error", e);
            }
        }
    }

    public SessionManager getSessionManager() {
        return (SessionManager) modules.get(SessionManager.class);
    }

    public MonitorManager getMonitorManager() {
        return (MonitorManager) modules.get(MonitorManager.class);
    }


    public MessageManager getMessageManager() {
        return (MessageManager) modules.get(MessageManager.class);
    }

    public ConnectionManager getConnectionManager() {
        return (ConnectionManager) modules.get(ConnectionManager.class);
    }


    public MonitorManager getLogManager() {
        return (MonitorManager) modules.get(MonitorManager.class);
    }

    /**
     * 启动服务实例
     */
    public void start() {

        try {
            initialize();
            // load all the modules
            loadModules();
            // Initize all the modules
            initModules();
            // Start all the modules
            startModules();

            // ---------------------------

            RUNNING = true;

            // service.execute(new MessageConsumer(this));
            // service.execute(new CombinConsumer(this));
            // service.execute(new RtuDatabaseConsumer(this));
            // service.execute(new BizDatabaseConsumer(this));

            System.out.println("RTU SERVER >> 湖北一方数据接收平台--接收服务启动完成.");


            startDate = System.currentTimeMillis();

        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage(), e);
            System.out.println("RTU SERVER >> 湖北一方数据接收平台.error");
            // shutdownServer();
        }

    }

    /**
     * 关闭服务实例
     */
    public void stop() {

        RUNNING = false;
        try {
            Thread.sleep(3 * 1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        System.out.println("正在关闭处理服务，请等待....");
        try {
            Thread.sleep(3 * 1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        // If we don't have modules then the server has already been shutdown
        if (modules.isEmpty()) {
            return;
        }
        // Get all modules and stop and destroy them
        for (Module module : modules.values()) {
            module.stop();
            module.destroy();
        }
        modules.clear();

        //TaskEngine.getInstance().shutdown();

        System.out.println("RTU SERVER >> Shutting down...");
    }

    public boolean running() {
        return RUNNING;
    }


    public long getStartDate() {
        return startDate;
    }

    /**
     * 获取消息总数
     *
     * @return
     */
    public int messageSize() {
        if (wc.get() == Integer.MAX_VALUE) {
            wc.set(0);
        }
        return wc.incrementAndGet();
    }


    public static void main(String[] args) {
        YFRtuServer server = YFRtuServer.getInstance();
        server.start();
    }

}
